//==============================================================================
//
//  File        : mmpf_sensor.c
//  Description : Sensor Control function
//  Author      : Penguin Torng
//  Revision    : 1.0
//
//==============================================================================

#include "includes_fw.h"
#if defined(DSC_MP3_P_FW)||defined(VIDEO_AAC_R_FW)||defined(VIDEO_AMR_R_FW)||(SENSOR_EN)
#include "lib_retina.h"
#include "mmp_reg_rawproc.h"
#include "mmp_reg_vif.h"
#include "mmp_reg_ibc.h"

#include "mmpf_display.h"
#include "mmpf_scaler.h"
#include "mmpf_sensor.h"
#include "mmpf_hif.h"
#include "mmpf_3gpmgr.h"
#include "mmpf_mp4venc.h"
#include "mmpf_rawproc.h"
#include "config_fw.h"
#include "mmpf_vif.h"
#include "mmp_reg_gpio.h"
#include "hdm_ctl.h"
#include "text_ctl.h"
#include "mmpf_dram.h"
#include "pcam_handler.h"
#include "pcam_dfu.h"
#include "mmpf_i2cm.h"
#if (SUPPORT_OSD_FUNC)
#include "pCam_osd_api.h"
#endif
#include "mmpf_dma.h"
#include "mmp_reg_dma.h"
//==============================================================================
//
//                              VARIABLES
//
//==============================================================================
/** @addtogroup MMPF_Sensor
@{
*/

extern 	MMPF_OS_FLAGID   SYS_Flag_Hif;
//MMP_UBYTE gbAFEnable;
extern	MMP_UBYTE	gbExposureDoneFrame[];
extern	MMP_UBYTE	gbVideoCaptureStart;
extern	MMP_ULONG   glPreviewBufAddr[2][4];
extern	MMP_ULONG   glPreviewUBufAddr[2][4];
extern	MMP_ULONG   glPreviewVBufAddr[2][4];
extern  MMP_UBYTE   gbPreviewBufferCount[];

#if (defined(ALL_FW)&&(PCAM_EN==0))
#if (LANDSCAPE_SUPPORT)&&(defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW)) 
extern  MMP_USHORT  gsPreviewBufWidth;
extern  MMP_USHORT  gsPreviewBufHeight;
extern  MMP_ULONG   glRotateBufAddr[2];
extern  MMP_ULONG   glRotateUBufAddr[2];
extern  MMP_ULONG   glRotateVBufAddr[2];
extern  MMP_UBYTE   gbRotateBufferCount;
extern  MMP_UBYTE   gbRotateCurBufIdx;
extern  MMP_UBYTE   gbRotateDoneBufIdx;
#endif

extern 	MMPF_DISPLAY_PREVIEW_MODE   gPreviewMode[];
extern  MMPF_DISPLAY_WINID  gPreviewWinID[];
#endif
extern	MMPF_IBC_LINK_TYPE	gIBCLinkType[];

static  MMP_BOOL    gbInStableMode = MMP_FALSE;

#if ((defined(DSC_MP3_P_FW)||(DSC_R_EN))&&(FDTC_SUPPORT == 1))
extern  MMPF_FDTC_ATTRIBUTE gFDTCAttribute;
#endif
#if (DYNAMIC_CONFIG_CACHEBUF == 1)
extern  void MMPF_MMU_ConfigFDTCWorkingBuffer(unsigned int startAddr, unsigned int endAddr, char cacheable);
#endif
MMP_BOOL    gbInFDTCMode = MMP_FALSE;

//MMP_USHORT  gsSensorLCModeWidth, gsSensorLCModeHeight;
//MMP_USHORT  gsSensorMCModeWidth, gsSensorMCModeHeight;
MMP_USHORT  gsSensorPreviewWidth[3], gsSensorPreviewHeight[3];

MMP_USHORT  gsCurPreviewMode, gsCurPhaseCount;
MMPF_SENSOR_FUNCTION *gsSensorFunction;
MMP_USHORT gsSensorMode;

//extern	MMPF_OS_SEMID   m_StartPreviewFrameEndSem;
//extern	MMPF_OS_SEMID	m_PreviewControlSem;
//extern	MMP_BOOL		m_bReceiveStopPreviewSig[MMPF_IBC_PIPE_MAX];
extern	MMP_BOOL		m_bWaitVIFEndSig;

extern MMPF_SENSOR_FUNCTION *SensorFunction_Module0;
#if (TOTAL_SENSOR_NUMBER >= 2)
extern MMPF_SENSOR_FUNCTION *SensorFunction_Module1;
#endif
static MMP_BOOL m_bRawPathPreview = MMP_FALSE;
MMP_BOOL m_bZeroShutterLagPath   = MMP_FALSE;        //Ted ZSL
static MMP_BOOL m_bRawStoreDownsample   = MMP_FALSE;
//static MMP_BOOL m_bDVSPathPreview       = MMP_FALSE;
#if 0//CAPTURE_BAYER_RAW_ENABLE==0
MMP_BOOL gbDVSStartSig = MMP_FALSE;
#else
extern MMP_BOOL gbDVSStartSig;
#endif
extern MMP_USHORT	gsPreviewPath;

extern	MMP_USHORT	m_gsISPCoreID;

extern MMP_BOOL    gbAutoFocus;

MMP_ULONG	m_glISPBufferStartAddr;
MMPF_SENSOR_3A_STATE    gb3AInitState = MMPF_SENSOR_3A_RESET ;

extern MMP_UBYTE gbSwitchSensor;

//------------------------------------------------------------------------------
//  Function    : MMPF_VIF_ISR
//  Description :
//------------------------------------------------------------------------------
MMP_ULONG glviftick = 0;
MMP_ULONG trycount = 0;
#include "mmpf_usbpccam.h"
extern MMP_ULONG   glPccamResolution;
extern MMP_ULONG glPCCamCnt;
extern volatile MMP_ULONG PTS;
extern MMP_ULONG glCPUFreq ;
#if (CUSTOMER == PNS)
extern MMP_UBYTE CROP_EN;
#endif
extern MMP_BOOL  gbMirrorFlip_flag;
extern MMP_UBYTE flip_enable, mirror_enable, black_image;
#if RAW_DATA_EN
extern MMP_USHORT gsFrameDataWithRaw, MD_x_res, MD_y_res;
MMP_BOOL gbEnAfter30P = 0;
#endif
MMP_ULONG glMDCnt = 0;
void MMPF_VIF_ISR(void)
{
    AITPS_VIF   pVIF = AITC_BASE_VIF;
    MMP_UBYTE   intsrc;
    //PCAM_USB_VIDEO_FORMAT vidFmt = pcam_get_info()->pCamVideoFormat;

    intsrc = pVIF->VIF_INT_CPU_SR[0] & pVIF->VIF_INT_CPU_EN[0];
    pVIF->VIF_INT_CPU_SR[0] = intsrc;

    //
    // OV2710 vertical blanking is too short
    // If zoom in Frame End, the preview is shaking,
    //
    #if 0
	if (intsrc & VIF_INT_FRM_END) {
        MMPF_Scaler_SetZoomOP();
        #if SUPPORT_DIGITAL_PAN
        MMPF_Scaler_SetPanTiltOP();
        #endif
	}
	#endif
	
	if (intsrc & VIF_INT_GRAB_END /*VIF_INT_FRM_END*/) {
        //dbg_printf(3,"[VIF_INT_GRAB_END] \r\n");
        //MMPF_Scaler_SetZoomOP();
        #if SUPPORT_DIGITAL_PAN
        //MMPF_Scaler_SetPanTiltOP();
        #endif
	}

    if (intsrc & VIF_INT_FRM_END) {
        if(gbMirrorFlip_flag == 1) {
            if(flip_enable || mirror_enable){
                if(flip_enable && mirror_enable)
                    gsSensorFunction->MMPF_Sensor_SetColorID(MMPF_SENSOR_ROTATE_RIGHT_180);
                else if(mirror_enable)
                    gsSensorFunction->MMPF_Sensor_SetColorID(MMPF_SENSOR_ROTATE_H_MIRROR);
                else if(flip_enable)
                    gsSensorFunction->MMPF_Sensor_SetColorID(MMPF_SENSOR_ROTATE_V_FLIP);
            }
            else{
                gsSensorFunction->MMPF_Sensor_SetColorID(MMPF_SENSOR_ROTATE_NO_ROTATE);
            }
            gbMirrorFlip_flag = 0;
        }
    	//dbg_printf(3,"[VIF_INT_FRM_END] \r\n");
#if RAW_DATA_EN
        glMDCnt++;
        if (gsFrameDataWithRaw&&gbEnAfter30P) {
            extern MMP_ERR MMPF_RAWPROC_GrabSensorData(MMP_BOOL bCapture,MMP_BOOL bWaitFinish);
            AITPS_RAWPROC pRAW = AITC_BASE_RAWPROC;

            #if SUPPORT_PIPE_Y && SUPPORT_AIT845x_MD
            extern MMPF_OS_FLAGID AIT845xMD_Flag;
            if((glMDCnt%6)==0){
                MMPF_OS_SetFlags(AIT845xMD_Flag, MD_FLAG_AIT845xMD, MMPF_OS_FLAG_SET);
                glMDCnt = 0;
            }
            #else
            extern void usb_fill_payload_header(MMP_UBYTE *frame_ptr, MMP_ULONG framelength, MMP_ULONG frameseq, MMP_ULONG flag,
                                                MMP_ULONG timestamp, MMP_USHORT w, MMP_USHORT h, MMP_USHORT framerate,
                                                MMP_UBYTE format_type, MMP_UBYTE ubPipe);
            MMP_ULONG jpegSize, buf_addr;
            FRAME_PAYLOAD_HEADER *yuv_ph;
            buf_addr = (MMP_ULONG)MMPF_Video_CurWrPtr(PIPE_G);
            yuv_ph = (FRAME_PAYLOAD_HEADER *) buf_addr;
            #if RAW_PROC_10_BIT_EN
            jpegSize = MD_x_res*MD_y_res*4/3;
            #else
            jpegSize = MD_x_res*MD_y_res;
            #endif
            glPCCamCnt++;
            //if(PH_GET_TX_CTL(yuv_ph->FRAME_H264_PH.dwFlag) == 0){
            usb_fill_payload_header((MMP_UBYTE *)buf_addr,jpegSize,glPCCamCnt,0,PTS,MD_x_res,MD_y_res, ISP_IF_AE_GetRealFPS(), ST_RAW, PIPE_G);
            //}
            #endif
            //MMPF_Video_UpdateWrPtr(PIPE_G);

            pRAW->RAWPROC_S_ADDR = (MMP_ULONG)MMPF_Video_CurWrPtr(PIPE_G)+FRAME_PAYLOAD_HEADER_SZ;
            MMPF_RAWPROC_GrabSensorData(MMP_TRUE, MMP_FALSE);
            
            #if SUPPORT_PIPE_Y
            if((glMDCnt%6)==0)
            gsFrameDataWithRaw = 0;
            #else
            MMPF_USB_ReleaseDm(PIPE_G);
            RTNA_DBG_Str3("RAW.R\r\n");
            #endif
            
        }
#endif
        //if(!((vidFmt==PCAM_USB_VIDEO_FORMAT_YUV422)&&(glPccamResolution==PCCAM_1280_720)))
        //MMPF_USB_ReleaseDm(0);  //Only one release in vif_frm_end by JengWei
    }

	if (intsrc & VIF_INT_LINE_0) {
	    glviftick++;
		//dbg_printf(3,"[VIF_INT_LINE_0] \r\n");
#if (CUSTOMER == PNS)	//Set Crop YUY2 function
		if(CROP_EN&&(gFramebaseCap.format==1)&&(glPccamResolution!=9)) {
			extern MMP_UBYTE gbPanTiltPathSel;
			pVIF->VIF_INT_CPU_SR[0]  = ( VIF_INT_GRAB_END );
	    	pVIF->VIF_INT_CPU_EN[0] |= ( VIF_INT_GRAB_END );
	    	gbPanTiltPathSel = 0xFF;
	    }
#endif
	}

	if (intsrc & VIF_INT_FRM_ST) {
        PTS =  MMPF_BSP_GetTick() * glCPUFreq + MMPF_BSP_GetTickClock()  ;
            //dbg_printf(3,"PTS : %x\r\n",PTS); 
#if 0
        dbg_printf(3,"**V_F_S** \r\n");
#endif
	}

    intsrc = pVIF->VIF_INT_CPU_SR[1] & pVIF->VIF_INT_CPU_EN[1];
    pVIF->VIF_INT_CPU_SR[1] = intsrc;

}


//------------------------------------------------------------------------------
//  Function    : MMPF_ISP_ISR
//  Description :
//------------------------------------------------------------------------------
#if DRAW_TEXT_FEATURE_EN==ON
extern ISP_UINT8 gDrawTextEn;
#endif
void MMPF_ISP_ISR(void)
{
     
    AITPS_ISP   pISP = AITC_BASE_ISP;
    MMP_UBYTE   intsrc;
    
    
    intsrc = pISP->ISP_INT_CPU_SR & pISP->ISP_INT_CPU_EN;
    pISP->ISP_INT_CPU_SR = intsrc;

    return;
  
    if(m_bRawPathPreview) {
        return ;
    }
    
    if (intsrc & ISP_INT_FRAME_START) {
		#if (USE_TASK_DO3A == 1)
		MMPF_OS_SetFlags(SYS_Flag_Hif, SYS_FLAG_ISP_AE_START, MMPF_OS_FLAG_SET); // Change to task handle the 3A.
		#else
		gsSensorFunction->MMPF_Sensor_DoAEOperation_ST();
		#endif
		
    }


    if (intsrc & ISP_INT_FRAME_END) {
#if 1   
            gsSensorFunction->MMPF_Sensor_DoAFOperation();  //change to frame End, suggest by Yanwei
	
			gsSensorFunction->MMPF_Sensor_DoAEOperation_END();
			
            ISP_IF_AWB_GetHWAcc(1);//a-liang move from MMPF_Sensor_DoAWBOperation 20121119
	#if DRAW_TEXT_FEATURE_EN==ON
			gDrawTextEn = (*(MMP_UBYTE*)0x800070C4) & 0x01;
			//only for test kyle
			//ISP_IF_F_SetImageEffect((*(MMP_UBYTE*)0x800070c4));
	#endif
	#if IQ_OPR_DMA_ON
		ISP_IF_IQ_UpdateOprtoHW(ISP_IQ_SWITCH_ALL, 0);
	#else
        if (((*(MMP_UBYTE*) 0x80007085) & 0x04) == 0)
   	    	gsSensorFunction->MMPF_Sensor_DoIQOperation();
	#endif		
#endif		
        //dbg_printf(3,"[ISP_INT_FRAME_END] \r\n");
    }

    if (intsrc & ISP_INT_AF_CALC_DONE) {
    }

}

void MMPF_Sensor_3A_SetInterrupt(ISP_UINT8 enable)
{
    //dbg_printf(1, " <snr_3a>%d ", enable); {int remove_this;}
	MMPF_Sensor_SetVIFInterrupt(VIF_INT_GRAB_END, enable);
	MMPF_Sensor_SetVIFInterrupt(VIF_INT_LINE_0, enable);
	MMPF_Sensor_SetVIFInterrupt(VIF_INT_FRM_END, enable);
	MMPF_Sensor_SetVIFInterrupt(VIF_INT_FRM_ST, enable);	 // CZ Sensor test code
	MMPF_Sensor_SetISPInterrupt(ISP_INT_AF_CALC_DONE , enable);
	MMPF_Sensor_SetISPInterrupt(ISP_INT_FRAME_START , enable);
	MMPF_Sensor_SetISPInterrupt(ISP_INT_FRAME_END   , enable);
}

MMP_ERR MMPF_Sensor_Set3AState(MMPF_SENSOR_3A_STATE state)
{
    gb3AInitState = state ;
    return MMP_ERR_NONE;
}

MMPF_SENSOR_3A_STATE MMPF_Sensor_Get3AState(void)
{
    return gb3AInitState ;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_GetParam
//  Description :
//------------------------------------------------------------------------------
/** @brief Get sesor related variables

Get sesor related variables

@param[in]  param_type  parameter type
@param[out] param       result

@return MMP_ERR_NONE
*/
MMP_ERR MMPF_Sensor_GetParam(MMPF_SENSOR_PARAM param_type, void* param)
{
    switch(param_type)
    {
    case MMPF_SENSOR_RAWPATH_PREVIEW_ENABLE:
       *((MMP_BOOL*)param) = m_bRawPathPreview;
        break;
    case MMPF_SENSOR_RAWPATH_STORE_DOWNSAMPLE:
        *((MMP_BOOL*)param) = m_bRawStoreDownsample;
        break;

    case MMPF_SENSOR_RAWPATH_ZEROSHUTTERLAG_ENABLE:
       *((MMP_BOOL*)param) = m_bZeroShutterLagPath;
        break;
    }
    
    return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetParam
//  Description :
//------------------------------------------------------------------------------
/** @brief Set sesor related variables

Set sesor related variables

@param[in]  param_type  parameter type
@param[out] param       result

@return MMP_ERR_NONE
*/
MMP_ERR MMPF_Sensor_SetParam(MMPF_SENSOR_PARAM param_type, void* param)
{
    switch (param_type) {
    case MMPF_SENSOR_RAWPATH_PREVIEW_ENABLE:
		m_bRawPathPreview = *((MMP_BOOL*)param);
        break;
    }
    
    return MMP_ERR_NONE;
}
//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_IsStableMode
//  Description :
//------------------------------------------------------------------------------

MMP_BOOL MMPF_Sensor_IsStableMode(void)
{
    return gbInStableMode;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_IsStableMode
//  Description :
//------------------------------------------------------------------------------

MMP_BOOL MMPF_Sensor_IsFDTCMode(void)
{
    return gbInFDTCMode;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_GetPreviewEffectNum
//  Description :
//------------------------------------------------------------------------------

MMP_ERR MMPF_Sensor_GetPreviewEffectNum(MMP_UBYTE *ubEffectNum)
{
    *ubEffectNum = 38;

    return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_WaitFrame
//  Description :
//------------------------------------------------------------------------------

MMP_ERR MMPF_Sensor_WaitFrame(MMP_USHORT usFrameCount)
{
	MMP_USHORT i;
	AITPS_VIF  pVIF = AITC_BASE_VIF;
	MMP_UBYTE   vid = 0;

	for (i = 0; i < usFrameCount; i++) {
		pVIF->VIF_INT_CPU_SR[vid] = VIF_INT_FRM_ST;
	    while (!(pVIF->VIF_INT_CPU_SR[vid] & VIF_INT_FRM_ST));
	}

	return MMP_ERR_NONE;
}


//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_CheckFrameStart
//  Description : porting function for venus driver
//------------------------------------------------------------------------------
#define VIF_WAIT_MS (1000)
MMP_ERR MMPF_Sensor_CheckFrameStart(MMP_USHORT usFrameCount)
{
	MMP_USHORT i;
	int wait_count = VIF_WAIT_MS ;
	MMP_BOOL    bEnable;
	AITPS_VIF  pVIF = AITC_BASE_VIF;
	MMP_UBYTE   vid = 0;

    MMPF_VIF_IsInterfaceEnable(&bEnable);

	for (i = 0; i < usFrameCount; i++) {
	    if ( bEnable ) {
                pVIF->VIF_INT_HOST_SR[vid] = VIF_INT_FRM_ST;
	        while (!(pVIF->VIF_INT_HOST_SR[vid] & VIF_INT_FRM_ST)){
 		    MMPF_OS_Sleep(1);
    	            wait_count-- ;
    	            if(wait_count <= 0) {
    	                return MMP_SENSOR_ERR_INITIALIZE ;
    	            }    
	    	}
	    }
	    else {
	        MMPF_OS_Sleep(100);
            return MMP_SENSOR_ERR_INITIALIZE_NONE;
	    }
	}

	return MMP_ERR_NONE;
}
//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_CheckFrameEnd
//  Description : porting function for venus driver
//------------------------------------------------------------------------------

MMP_ERR MMPF_Sensor_CheckFrameEnd(MMP_USHORT usFrameCount)
{
	MMP_USHORT i;
    int wait_count = VIF_WAIT_MS;
    MMP_BOOL   bEnable;
	AITPS_VIF  pVIF = AITC_BASE_VIF;
	MMP_UBYTE   vid = 0;

    MMPF_VIF_IsInterfaceEnable(&bEnable);

    for (i = 0; i < usFrameCount; i++) {
        if ( bEnable ) {
    	    pVIF->VIF_INT_HOST_SR[vid] = VIF_INT_FRM_END;
            while (!(pVIF->VIF_INT_HOST_SR[vid] & VIF_INT_FRM_END)) {
                MMPF_OS_Sleep(1);
                wait_count-- ;
                if(wait_count <= 0) {
                    return MMP_SENSOR_ERR_INITIALIZE ;
                }    
        	}
        }
        else {
            MMPF_OS_Sleep(100);
            return MMP_SENSOR_ERR_INITIALIZE_NONE;
        }
    }

	return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetVIFInterrupt
//  Description : porting function for venus driver
//------------------------------------------------------------------------------
MMP_ERR MMPF_Sensor_SetVIFInterrupt(MMP_UBYTE ubFlag, MMP_BOOL bEnable)
{
	AITPS_VIF  pVIF = AITC_BASE_VIF;
	MMP_UBYTE   vid = 0;

	//RTNA_DBG_Str(0, "Venus Interrupt Enable function : ");
	//RTNA_DBG_Byte(0, ubFlag);
	//if (bEnable)
	//	RTNA_DBG_Str(0, " ON\r\n");
	//else
	//	RTNA_DBG_Str(0, " OFF\r\n");

	if (bEnable) {
		pVIF->VIF_INT_CPU_SR[vid] = ubFlag;
		pVIF->VIF_INT_CPU_EN[vid] |= ubFlag;
	} 
	else {
		pVIF->VIF_INT_CPU_EN[vid] &= ~ubFlag;
	}

	return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_SetISPInterrupt
//  Description : porting function for venus driver
//------------------------------------------------------------------------------
MMP_ERR MMPF_Sensor_SetISPInterrupt(MMP_UBYTE ubFlag, MMP_BOOL bEnable)
{
    AITPS_ISP   pISP = AITC_BASE_ISP;

	if (bEnable) {
		pISP->ISP_INT_CPU_SR = ubFlag;
		pISP->ISP_INT_CPU_EN |= ubFlag;
	} 
	else {
		pISP->ISP_INT_CPU_EN &= ~ubFlag;
	}

	return MMP_ERR_NONE;
}

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_ConfigFunctions
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Sensor_ConfigFunctions(MMP_USHORT usSensorID)
{
    switch(usSensorID){
    case 0:
#if SUPPORT_SWITCH_CAMERA
        gsSensorFunction = ((gbSwitchSensor==MAIN_SENSOR)?SensorFunction_Module0:SensorFunction_Module1);
#else
        gsSensorFunction = SensorFunction_Module0;
#endif
        break;
    #if (TOTAL_SENSOR_NUMBER >= 2)        
    case 1:
        gsSensorFunction = SensorFunction_Module1;
        break;
    #endif        
    default:
        break;
    }

	return MMP_ERR_NONE;
}

#if DRAM_SIZE <= 2
static MMP_ULONG ISP_BUFFER_SIZE = 0;
#endif

MMP_ULONG MMPF_Sensor_CalculateBufferSize (void)
{
    MMP_ULONG   total_size = 0;

    #if (CHIP == VSN_V2)
    total_size = ISP_BUFFER_SIZE;
    #endif

    return total_size;
}

#if DRAM_SIZE <= 2
void MMPF_Sensor_SetBufferSize (const MMP_ULONG buffer_size)
{
    ISP_BUFFER_SIZE = buffer_size;
}
#endif

#if DRAM_SIZE > 2
//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_AllocateBuffer
//  Description :
//------------------------------------------------------------------------------
MMP_ERR MMPF_Sensor_AllocateBuffer(MMP_ULONG ulStartAddr)
{
    #if (CHIP == VSN_V2)
	m_glISPBufferStartAddr = ulStartAddr;
	#endif

	return MMP_ERR_NONE;
}
#endif

//------------------------------------------------------------------------------
//  Function    : MMPF_Sensor_ProcessCmd
//  Description :
//------------------------------------------------------------------------------
#if PCAM_EN==0
MMP_ERR MMPF_Sensor_ProcessCmd(void)
{
    MMP_ULONG   ulParameter[6], i;
    MMP_USHORT  usData, usBaseN, usCurrentN;
    MMP_USHORT	usCommand;
    MMP_USHORT  usIBCPipe;
    MMP_ERR		err;
    MMP_UBYTE	ubEffectNum;
    MMP_ULONG	ulSize;

	usCommand = MMPF_HIF_GetCmd();
    //GBL_HOST_PARM only has 24 bytes (12 words or 6 ulong int)
	for (i = 0; i < 24; i += 4)
		ulParameter[i >> 2] = MMPF_HIF_CmdGetParameterL(i);
	
	MMPF_HIF_SetCmdStatus(SENSOR_CMD_IN_EXEC);	
	MMPF_HIF_ClearCmd();

    switch (usCommand & (FUNC_MASK|GRP_MASK)) {
    
    case HIF_CMD_SENSOR_CONTROL:
        switch (usCommand & SUB_MASK) {
        case SET_REGISTER:
            gsSensorFunction->MMPF_Sensor_SetReg((MMP_USHORT)ulParameter[0], (MMP_USHORT)(ulParameter[0] >> 16));
            break;
        case GET_REGISTER:
            gsSensorFunction->MMPF_Sensor_GetReg((MMP_USHORT)ulParameter[0], &usData);
			MMPF_HIF_CmdSetParameterW(0, usData);
            break;
        }
        break;
    case HIF_CMD_SET_PREVIEW_MODE:
        if ((usCommand & ENABLE_PREVIEW) == ENABLE_PREVIEW) {
			MMPF_HIF_CmdSetParameterL(0, (MMP_ULONG)MMPF_Display_StartPreview((MMP_USHORT)ulParameter[0], (MMP_BOOL)ulParameter[1]));
        }
        else {
            MMPF_Display_StopPreview((MMP_USHORT)ulParameter[0]);
		}
        break;
    case HIF_CMD_INIT_SENSOR:
        MMPF_Sensor_ConfigFunctions((MMP_USHORT)ulParameter[0]);
        gsSensorFunction->MMPF_Sensor_SetFrameRate((MMP_USHORT)((ulParameter[0] & 0xFFFF0000) >> 16));
        gsSensorFunction->MMPF_Sensor_InitializeVIF();
		gsSensorFunction->MMPF_Sensor_InitializeISP();
		err = gsSensorFunction->MMPF_Sensor_Initialize();

		MMPF_HIF_CmdSetParameterL(0, err);	//Return return code [0:success, 1:fail]		
		if (err) {		
			return err;
		}
        gsCurPreviewMode = (MMP_USHORT)ulParameter[1];
        gsCurPhaseCount = (MMP_USHORT)((ulParameter[1] & 0xFFFF0000) >> 16);
        gsSensorFunction->MMPF_Sensor_SetPreviewMode(gsCurPreviewMode);
        break;
    case HIF_CMD_SET_SENSOR_MODE:
    	gsSensorMode = (MMP_USHORT)ulParameter[0];
    	break;
    case HIF_CMD_POWERDOWN_SENSOR:
        MMPF_Sensor_ConfigFunctions((MMP_USHORT)ulParameter[0]);
        gsSensorFunction->MMPF_Sensor_PowerDown();
        break;
    case HIF_CMD_SET_ZOOM_PARAM:
        switch (usCommand & SUB_MASK) {
        case ZOOM_PARAMTER:
            MMPF_Scaler_SetZoomParams((MMP_USHORT)ulParameter[5],  
                                      (MMPF_SCALER_GRABCONTROL *)&ulParameter[2],
                                      (MMP_USHORT)ulParameter[1],
                                      (MMP_USHORT)(ulParameter[1] >> 16),
                                      (MMP_USHORT)ulParameter[0],
                                      (MMP_USHORT)(ulParameter[0] >> 16));
            break;
        case SINGLE_ZOOM_RANGE:
            MMPF_Scaler_SetZoomRange((MMP_USHORT)ulParameter[0],
                                     (MMP_USHORT)(ulParameter[0] >> 16),
                                     (MMP_USHORT)ulParameter[1]);
            break;
        case ZOOM_DIRECTION:
            MMPF_Scaler_SetDigitalZoom((MMP_USHORT)ulParameter[0],
                                       (MMP_USHORT)(ulParameter[0] >> 16), 
                                       (MMPF_SCALER_PATH)ulParameter[1], 
                                        (MMP_USHORT)(ulParameter[1] >> 16));
            break;
        }
        break;
    case HIF_CMD_GET_ZOOM_PARAM:
        switch (usCommand & SUB_MASK) {
        case ZOOM_INFO:
            MMPF_Scaler_GetZoomInfo((MMP_USHORT)ulParameter[0], &usBaseN, &usCurrentN);
            MMPF_HIF_CmdSetParameterW(0, usBaseN);
            MMPF_HIF_CmdSetParameterW(2, usCurrentN);
            break;
        }
        break;
    case HIF_CMD_SET_ZOOMOP:
        MMPF_Scaler_SetDigitalZoomOP((MMP_USHORT)ulParameter[0],
                                       (MMP_USHORT)(ulParameter[0] >> 16), 
                                       (MMPF_SCALER_PATH)ulParameter[1]);
        break;
    case HIF_CMD_3A_FUNCTION:
        switch (usCommand & SUB_MASK) {
        	case SET_AF_WIN:
               	gsSensorFunction->SetAFWin((MMP_USHORT)ulParameter[0], 
					(MMP_USHORT)(ulParameter[0] >> 16), (MMP_USHORT)ulParameter[1],
					(MMP_USHORT)(ulParameter[1] >> 16), (MMP_USHORT)ulParameter[2],
					(MMP_USHORT)(ulParameter[2] >> 16), (MMP_USHORT)ulParameter[3]);
                break;
            case AUTO_FOCUS:
			//gbInFDTCMode  = MMP_FALSE; 
               	gsSensorFunction->SetAFEnable(1);
                break;
            case FOCUS_INFINITY:
             	if (gsSensorFunction->GetAFEnable() == 1) {
                    RTNA_DBG_Str(3, "ERROR: MMPF_SENSOR_ProcessCmd()->FOCUS_INFINITY --> gbAFEnable ==1 \r\n");
                }
                gsSensorFunction->MMPF_Sensor_SetAFPosition(0);
                break;
            case SET_LENS_POSITION:
             	if (gsSensorFunction->GetAFEnable() == 1) {
                    RTNA_DBG_Str(3, "ERROR: MMPF_SENSOR_ProcessCmd()->SET_LENS_POS --> gbAFEnable ==1 \r\n");
                }
                gsSensorFunction->MMPF_Sensor_SetAFPosition((MMP_USHORT)ulParameter[0]);
                break;
            case LIGHT_FREQ:
                gsSensorFunction->MMPF_SetLightFreq((MMP_USHORT)ulParameter[0]);
                break;
            case AWB_TYPE:
                gsSensorFunction->MMPF_Sensor_SetAWBType((MMP_UBYTE)ulParameter[0] );
                break;
            case AE_TYPE:
                gsSensorFunction->MMPF_Sensor_SetAEEnable((MMP_UBYTE)ulParameter[0]);
                break;
            case NIGHT_MODE:
            	if ((ulParameter[0] & 0xFFFF) == 0)
                	gsSensorFunction->MMPF_Sensor_SetImageScene(0);
                else
                	gsSensorFunction->MMPF_Sensor_SetImageScene(7);	
                break;
            case COLOR_CONTRAST:
                gsSensorFunction->MMPF_Sensor_SetContrast((MMP_UBYTE)(ulParameter[0]&0xFF));
                break;
            case COLOR_SATURATION:
				gsSensorFunction->MMPF_Sensor_SetSaturation((MMP_UBYTE)(ulParameter[0]&0xFF));
                break;
            case COLOR_SHARPNESS:
                gsSensorFunction->MMPF_Sensor_SetSharpness((MMP_UBYTE)(ulParameter[0]&0xFF));
                break;
            case SET_AF_MODE:
	            gsSensorFunction->MMPF_Sensor_SetAFMode((MMP_UBYTE)(ulParameter[0]&0xFF));
	            break;
	        case GET_AF_STATUS:
	        	MMPF_HIF_CmdSetParameterB(0, gsSensorFunction->GetAFEnable());
	        	break;
			case SET_HW_BUFFER:
				MMPF_HIF_CmdSetParameterL(0, MMPF_Sensor_AllocateBuffer(ulParameter[0]));
	        	break;
         }
        break;
    case HIF_CMD_GET_EFFECT_NUM:
    	MMPF_Sensor_GetPreviewEffectNum(&ubEffectNum);
    	MMPF_HIF_CmdSetParameterW(0, ubEffectNum);
        break;
    case HIF_CMD_SET_PREVIEW_EFFECT:
    	gsSensorFunction->MMPF_Sensor_SetImageEffect((MMP_UBYTE)ulParameter[0]);
        break;
    case HIF_CMD_SET_EXPOSURE_VALUE:
    	gsSensorFunction->MMPF_Sensor_SetExposureValue((MMP_USHORT)ulParameter[0]);
        break;		        
    case HIF_CMD_SET_PREVIEW_BUF:
        switch (usCommand & SUB_MASK) {
		case BUFFER_ADDRESS:
			glPreviewBufAddr[(MMP_USHORT)ulParameter[0]][(ulParameter[0] >> 16) & 0xFF] = ulParameter[1];
			glPreviewUBufAddr[(MMP_USHORT)ulParameter[0]][(ulParameter[0] >> 16) & 0xFF] = ulParameter[2];
			glPreviewVBufAddr[(MMP_USHORT)ulParameter[0]][(ulParameter[0] >> 16) & 0xFF] = ulParameter[3];
			break;
		case BUFFER_COUNT:
			gbPreviewBufferCount[(MMP_USHORT)ulParameter[0]] = (MMP_UBYTE)(ulParameter[0] >> 16);
			break;
        #if (LANDSCAPE_SUPPORT)&&(defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW))
        case BUFFER_WIDTH:
            gsPreviewBufWidth = (MMP_USHORT)ulParameter[0];
            break;
        case BUFFER_HEIGHT:
            gsPreviewBufHeight = (MMP_USHORT)ulParameter[0];
            break;
        #endif
        }
        break;
        
    #if (LANDSCAPE_SUPPORT)&&(defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW))
    case HIF_CMD_SET_ROTATE_BUF:
        switch (usCommand & SUB_MASK) {
		case BUFFER_ADDRESS:
			glRotateBufAddr[(MMP_USHORT)ulParameter[0]] = ulParameter[1];
			glRotateUBufAddr[(MMP_USHORT)ulParameter[0]] = ulParameter[2];
			glRotateVBufAddr[(MMP_USHORT)ulParameter[0]] = ulParameter[3];
			break;
		case BUFFER_COUNT:
			gbRotateCurBufIdx = 0;
			gbRotateDoneBufIdx = 0;
			gbRotateBufferCount = (MMP_UBYTE)ulParameter[0];
			break;
        }
        break;
    #endif

    case HIF_CMD_SET_IBC_LINK_MODE:
        switch (usCommand & SUB_MASK) {
		case LINK_NONE:
			gIBCLinkType[(MMP_USHORT)ulParameter[0]] = MMPF_IBC_LINK_NONE;
			break;
		case LINK_DISPLAY:
			gIBCLinkType[(MMP_USHORT)ulParameter[0]] |= MMPF_IBC_LINK_DISPLAY;
			gPreviewMode[(MMP_USHORT)ulParameter[0]] = (MMP_USHORT)(ulParameter[0] >> 16);
			gPreviewWinID[(MMP_USHORT)ulParameter[0]] = (MMPF_DISPLAY_WINID)ulParameter[1];
			break;
		case LINK_VIDEO:
			gIBCLinkType[(MMP_USHORT)ulParameter[0]] |= MMPF_IBC_LINK_VIDEO;
        	break;
        #if (LANDSCAPE_SUPPORT)&&(defined(ALL_FW)||defined(DSC_MP3_P_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW))
		case LINK_DMA:
            gIBCLinkType[(MMP_USHORT)ulParameter[0]] |= MMPF_IBC_LINK_ROTATE;
            gPreviewMode[(MMP_USHORT)ulParameter[0]] = (MMP_USHORT)(ulParameter[0] >> 16);
            gPreviewWinID[(MMP_USHORT)ulParameter[0]] = (MMPF_DISPLAY_WINID)ulParameter[1];
            break;
        #endif
        #if ((defined(DSC_MP3_P_FW)||(DSC_R_EN))&&(FDTC_SUPPORT == 1))
        case LINK_FDTC:
            gFDTCAttribute.usFdtcIBCPipe = (MMP_USHORT)ulParameter[0];
			gIBCLinkType[gFDTCAttribute.usFdtcIBCPipe] |= MMPF_IBC_LINK_FDTC;
        	break;
        #endif
        case LINK_GRAPHIC:
            gIBCLinkType[(MMP_USHORT)ulParameter[0]] |= MMPF_IBC_LINK_GRAPHIC;
            break;
        case UNLINK_GRAPHIC:
            gIBCLinkType[(MMP_USHORT)ulParameter[0]] &= ~MMPF_IBC_LINK_GRAPHIC;
            break;
        }
        break;
    case HIF_CMD_SET_STABLE_STATE: 
        gsSensorFunction->MMPF_SetStableState((MMP_BOOL)ulParameter[0]);
        gbInStableMode = (MMP_BOOL)ulParameter[1];
        break;

    case HIF_CMD_SET_HISTEQ_STATE: 
        gsSensorFunction->MMPF_SetHistEQState((MMP_BOOL)ulParameter[0]);
        break;
    
    case HIF_CMD_SENSOR_PREVIEW_MODE:
        if(gsCurPreviewMode != (MMP_USHORT)ulParameter[0]) {
            gsSensorFunction->MMPF_Sensor_SetPreviewMode((MMP_USHORT)ulParameter[0]);
        }
        break;
    case HIF_CMD_SET_AE_MODE:
        gsSensorFunction->MMPF_Sensor_SetAEMode((MMP_USHORT)ulParameter[0], (MMP_USHORT)((ulParameter[0] & 0xFFFF0000) >> 16));
        break;
    case HIF_CMD_GET_PREVIEW_BUF:
        usIBCPipe = (MMP_USHORT)ulParameter[0];
        MMPF_HIF_CmdSetParameterL(0, glPreviewBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]]);
        MMPF_HIF_CmdSetParameterL(4, glPreviewUBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]]);
        MMPF_HIF_CmdSetParameterL(8, glPreviewVBufAddr[usIBCPipe][gbExposureDoneFrame[usIBCPipe]]);
        break;
    case HIF_CMD_SET_RAW_PREVIEW:
        switch (usCommand & SUB_MASK) {
        case RESET_PREVIEW_ATTRIBUTE:
            MMPF_RAWPROC_ResetPreviewAttribue();
            break;
        case ENABLE_RAWPREVIEW:
            MMPF_RAWPROC_GetVIFSetting();
            m_bRawPathPreview = ulParameter[0];
            if(!m_bRawPathPreview) {
                MMPF_RAWPROC_ResetZoomOP();
            }
            
            break;
        case ENABLE_ZEROSHUTTERLAG_PATH:        //Ted ZSL
            m_bZeroShutterLagPath = ulParameter[0];
            break;
        #if (defined(ALL_FW)||defined(VIDEO_AMR_R_FW)||defined(VIDEO_AAC_R_FW))
        case ENABLE_DVSPREVIEW:
            m_bDVSPathPreview = ulParameter[0];
            break;
        case SET_STORE_RANGE:
            MMPF_RAWPROC_SetStoreRange(ulParameter[0], ulParameter[1]);
            break;
        case SET_FETCH_RANGE:
            MMPF_RAWPROC_SetFetchRange(ulParameter[0], ulParameter[1]);
            break;
        #endif
        case ENABLE_RAWSTORE:
            MMPF_RAWPROC_EnableRawPath(ulParameter[0]);
            break;
		case RAWSTORE_ADDR:
		    MMPF_RAWPROC_ConfigRawPathMemory(ulParameter[0],ulParameter[1],ulParameter[2]);
		    break;
		case RAWSTORE_BAYER_ADDR:
            for (i = 0; i < (MMP_UBYTE)(ulParameter[0] & 0x000000FF); i++) {
                MMPF_RAWPROC_SetRawBuffer(i, ulParameter[i+1]);
		}
        break;        
        case RAWSTORE_LUMA_ADDR:
            for (i = 0; i < (MMP_UBYTE)(ulParameter[0] & 0x000000FF); i++) {
                MMPF_RAWPROC_SetLumaBuffer(i, ulParameter[i+1]);
            }
        break;        
        case START_DVS_ME:
            gbDVSStartSig = (MMP_BOOL)(ulParameter[0] & 0xFF);
            break;
		case ENABLE_RAW_DOWNSAMPLE:
		    MMPF_RAWPROC_EnableDownsample(ulParameter[0],ulParameter[1]);
		    
		    m_bRawStoreDownsample = ulParameter[0];
		    break;
		}
        break;  
    }

    MMPF_HIF_ClearCmdStatus(SENSOR_CMD_IN_EXEC);
    return 0;
}
#endif

#if PCAM_EN==1
extern MMP_USHORT  gsSensorPreviewWidth[], gsSensorPreviewHeight[];
MMP_ERR MMPF_Sensor_Initialize(MMP_USHORT usSensorID, MMP_UBYTE ubFrameRate,MMP_UBYTE ubPreviewMode)
{
    MMP_ERR err = MMP_ERR_NONE ;
    MMPF_Sensor_ConfigFunctions((MMP_USHORT)usSensorID);
    gsSensorFunction->MMPF_Sensor_SetFrameRate(ubFrameRate);
    gsSensorFunction->MMPF_Sensor_InitializeVIF();
    if(MMPF_Sensor_Get3AState()==MMPF_SENSOR_3A_RESET) {
	    gsSensorFunction->MMPF_Sensor_InitializeISP();
	    if (USB_ApplyCaliData(usSensorID)) {
	        DBG_S(1, "[ERR] Unable to apply cali data.\r\n");
	    }
        MMPF_Sensor_Set3AState(MMPF_SENSOR_3A_SET);
    }
    err = gsSensorFunction->MMPF_Sensor_Initialize();
    if(err) {
        dbg_printf(3, "[ERR] Sensor init x%X\r\n", err);
        return err;
	}
    #if ((CUSTOMER == ASU) && (MODEL == 1))
#if SUPPORT_SWITCH_CAMERA
    if(gbSwitchSensor==SUB_SENSOR)//flip the 5M sensor
#else
    if(usSensorID == 1)//flip the 5M sensor
#endif
    {        
    	gsSensorFunction->MMPF_Sensor_SetColorID(MMPF_SENSOR_ROTATE_V_FLIP);
    }
#if SUPPORT_SWITCH_CAMERA
    if(gbSwitchSensor==MAIN_SENSOR)//MIRROR the HD sensor
#else
    if(usSensorID == 0)//mirror the HD sensor
#endif
    {
    	gsSensorFunction->MMPF_Sensor_SetColorID(MMPF_SENSOR_ROTATE_H_MIRROR);
    }
    #endif
    //gsCurPreviewMode = (MMP_USHORT)ubPreviewMode;
    // gsCurPhaseCount = (MMP_USHORT)ubPhaseCount ;
    //gsSensorFunction->MMPF_Sensor_SetPreviewMode(gsCurPreviewMode);
    return err ;
}

//MMP_ERR MMPF_Sensor_SetPreviewEffect(MMP_UBYTE ubEffectID)
//{
//    gsSensorFunction->MMPF_Sensor_SetImageEffect(ubEffectID);
//    return MMP_ERR_NONE ;
//}

MMP_ERR MMPF_Sensor_PreviewMode(MMP_BOOL ubEnable,MMP_USHORT usIBCPipe,MMP_BOOL bCheckFrameEnd)
{
    if (ubEnable) {
		return MMPF_Display_StartPreview(usIBCPipe, bCheckFrameEnd);
    }
    else {
        return MMPF_Display_StopPreview(usIBCPipe );
	}
}



MMP_ERR MMPF_Sensor_AutoFocus(void)
{
	if(gbAutoFocus == MMP_TRUE){
        gsSensorFunction->SetAFEnable(1);
    }
    return MMP_ERR_NONE;
}

MMP_ERR MMPF_Sensor_SetSensorReg(MMP_USHORT usAddr, MMP_USHORT usData)
{
    return gsSensorFunction->MMPF_Sensor_SetReg(usAddr, usData);
}

MMP_ERR MMPF_Sensor_GetSensorReg(MMP_USHORT usAddr,MMP_USHORT usData)
{
    return gsSensorFunction->MMPF_Sensor_GetReg(usAddr,&usData); 
}

MMP_ERR MMPF_Sensor_PowerDown(MMP_USHORT usSensorID)
{
    MMPF_Sensor_ConfigFunctions(usSensorID);
    return gsSensorFunction->MMPF_Sensor_PowerDown();
}
#endif

//------------------------------------------------------------------------------
//  Function    : DSC_Task
//  Description : DSC main function
//------------------------------------------------------------------------------
extern MMP_BOOL    gbAutoFocus;
extern volatile MMP_UBYTE   gbDramID;
extern MMP_UBYTE  gbCurrentSensor;

#if (SUPPORT_OSD_FUNC)
MMP_BYTE strCustomerData[32] = {NULL};
//MMP_BYTE strCustomerData[32] = {'(', 'A', 'I', 'T', '-', 'I', 'P', 'C', 'A', 'M', ')'};
extern MMP_BYTE 		strTimeDate[];
extern MMP_ULONG OSD_CurrentW[],OSD_CurrentH[];
extern MMP_ULONG OSD_FontW[],OSD_FontH[];
extern MMP_USHORT gsOSD_WIDTH_MAX_WORD;
extern MMP_UBYTE gbOSDForeColorY;
extern MMP_USHORT gsOSDForeColorUV;
extern MMP_UBYTE gbOSDBackColorY;
extern MMP_USHORT gsOSDBackColorUV;
extern MMP_UBYTE gbOSDWordCntChange;
extern MMP_UBYTE ubOSDTimeFmt;
#if (MOVE_OSD_USING_DMA)
MMP_ULONG glOSDBufferYAddr[2], glOSDBufferUVAddr[2];
MMP_ULONG glOSDBufferYSize[2], glOSDBufferUVSize[2];
MMPF_DMA_M_LOFFS_DATA       gOSDFrameOffset = {20*16, 1280, 20*16, 1280};
extern MMP_USHORT m_usOsdStartXOffset, m_usOsdStartYoffset;
MMP_USHORT gsOSDLineNum;
extern MMP_ULONG glOSDStartBufAddr;
#endif
#endif

#if (SUPPORT_OSD_FUNC) && (MOVE_OSD_USING_DMA)
MMP_ULONG AllocateOSDYUVBuffer(MMP_ULONG startaddr)
{
    MMP_ULONG i;
    MMP_USHORT *UVptr;
    MMP_ULONG cur_addr, buf_size;
    
    cur_addr = startaddr;
    buf_size = 0;
        
	glOSDBufferYSize[0] = (gsOSD_WIDTH_MAX_WORD*OSD_FontW[0])*(OSD_FontH[0]*OSD_HEIGHT_MAX_LINE);  // 
	//glOSDBufferYAddr[0] = (MMP_ULONG) MMPF_SYS_AllocFB("OSD Buffer0 Y", glOSDBufferYSize[0], 32);
	glOSDBufferYAddr[0] = cur_addr;
	cur_addr += ((glOSDBufferYSize[0] + 31) & (-32));
	buf_size += ((glOSDBufferYSize[0] + 31) & (-32));
    MEMSET((void*)glOSDBufferYAddr[0], gbOSDBackColorY, glOSDBufferYSize[0]);

	glOSDBufferUVSize[0] = (gsOSD_WIDTH_MAX_WORD*OSD_FontW[0])*(OSD_FontH[0]*OSD_HEIGHT_MAX_LINE) / 2;  // 
	//glOSDBufferUVAddr[0] = (MMP_ULONG) MMPF_SYS_AllocFB("OSD Buffer0 UV", glOSDBufferUVSize[0], 32);
	glOSDBufferUVAddr[0] = cur_addr;
	cur_addr += ((glOSDBufferUVSize[0] + 31) & (-32));
	buf_size += ((glOSDBufferUVSize[0] + 31) & (-32));
    UVptr = (MMP_USHORT *)(glOSDBufferUVAddr[0]);
    for(i = 0 ; i < glOSDBufferUVSize[0]/2 ; i++){
        *(UVptr + i) = gsOSDBackColorUV;
    } 

	glOSDBufferYSize[1] = (gsOSD_WIDTH_MAX_WORD*OSD_FontW[1])*(OSD_FontH[1]*OSD_HEIGHT_MAX_LINE);  // 
	//glOSDBufferYAddr[1] = (MMP_ULONG) MMPF_SYS_AllocFB("OSD Buffer1 Y", glOSDBufferYSize[1], 32);
	glOSDBufferYAddr[1] = cur_addr;
	cur_addr += ((glOSDBufferYSize[1] + 31) & (-32));
	buf_size += ((glOSDBufferYSize[1] + 31) & (-32));
    MEMSET((void*)glOSDBufferYAddr[1], gbOSDBackColorY, glOSDBufferYSize[1]);

	glOSDBufferUVSize[1] = (gsOSD_WIDTH_MAX_WORD*OSD_FontW[1])*(OSD_FontH[1]*OSD_HEIGHT_MAX_LINE) / 2;  // 
	//glOSDBufferUVAddr[1] = (MMP_ULONG) MMPF_SYS_AllocFB("OSD Buffer1 UV", glOSDBufferUVSize[1], 32);
	glOSDBufferUVAddr[1] = cur_addr;
	cur_addr += ((glOSDBufferUVSize[1] + 31) & (-32));
	buf_size += ((glOSDBufferUVSize[1] + 31) & (-32));
    UVptr = (MMP_USHORT *)(glOSDBufferUVAddr[1]);
    for(i = 0 ; i < glOSDBufferUVSize[1]/2 ; i++){
        *(UVptr + i) = gsOSDBackColorUV;
    } 

    dbg_printf(3, "[0]OSDBufferYAddr = x%X(x%X), UVAddr = x%X(x%X)\r\n", glOSDBufferYAddr[0], glOSDBufferYSize[0], glOSDBufferUVAddr[0], glOSDBufferUVSize[0]);
    dbg_printf(3, "[1]OSDBufferYAddr = x%X(x%X), UVAddr = x%X(x%X)\r\n", glOSDBufferYAddr[1], glOSDBufferYSize[1], glOSDBufferUVAddr[1], glOSDBufferUVSize[1]);

    return buf_size;
}
#endif

void SENSOR_Task()
{
    AITPS_AIC   pAIC = AITC_BASE_AIC;
    //AITPS_GPIO  pGPIO = AITC_BASE_GPIO;
    //AITPS_PAD   pPAD = AITC_BASE_PAD;
    AITPS_GBL   pGBL = AITC_BASE_GBL;

    MMPF_OS_FLAGS flags;
    MMPF_OS_FLAGS waitFlags;
#if (SUPPORT_OSD_FUNC)
    PCAM_USB_VIDEO_FORMAT vidFmt;
#if (MOVE_OSD_USING_DMA == 0)
    AITPS_IBC   pIBC    = AITC_BASE_IBC;
    volatile AITPS_IBCP pIbcPipeCtl;
    MMP_ULONG   y_buf_addr, u_buf_addr;
#endif
#endif

    RTNA_DBG_Str(0, "SENSOR_Task()\r\n"); // Rename to MMPF ?

    // Open VIF interrupt for C3A operation
    RTNA_AIC_Open(pAIC, AIC_SRC_VIF, vif_isr_a,
                AIC_INT_TO_IRQ | AIC_SRCTYPE_HIGH_LEVEL_SENSITIVE | 3);
    RTNA_AIC_IRQ_Dis(pAIC, AIC_SRC_VIF);                
    //RTNA_AIC_IRQ_En(pAIC, AIC_SRC_VIF);

    // Open ISP interrupt for digital zoom operation
    RTNA_AIC_Open(pAIC, AIC_SRC_ISP, isp_isr_a,
                AIC_INT_TO_IRQ | AIC_SRCTYPE_HIGH_LEVEL_SENSITIVE | 3); //Patrick
    //RTNA_AIC_IRQ_En(pAIC, AIC_SRC_ISP);
    RTNA_AIC_IRQ_Dis(pAIC, AIC_SRC_ISP);

    RTNA_AIC_Open(pAIC, AIC_SRC_IBC, ibc_isr_a,
                AIC_INT_TO_IRQ | AIC_SRCTYPE_HIGH_LEVEL_SENSITIVE | 3);
	//RTNA_AIC_IRQ_En(pAIC, AIC_SRC_IBC);   
    RTNA_AIC_IRQ_Dis(pAIC, AIC_SRC_IBC); 

#if JTAG_DBG_EN==0
    RTNA_DBG_Str(0,"Disable JTAG interface\r\n");	
    //pGBL->GBL_CPU_TEST_MODE &= ~(ARM_JTAG_MODE_EN);  
#endif	

    if((gbDramID == MMPF_DRAMID_WINBOND_SDR16) || (gbDramID == MMPF_DRAMID_WINBOND_SDR16_1_8V)){
        pGBL->GBL_IO_CTL5 |= (1 << GPIO_SENSOR_PSEN);
        GPIO_OutputControl(GPIO_SENSOR_PSEN, FALSE);
    }

    #if (CUSTOMER == NMG)  
    #if (MicSource==MicInPathI2S)
    GPIO_OutputControl(CAM_EN, TRUE);  // turn on WM8737 ADC
    #else
    GPIO_OutputControl(CAM_EN, FALSE);
    #endif
    GPIO_OutputControl(AF_EN, FALSE);
    GPIO_OutputControl(LED_READY, FALSE);
    #endif

    #if (CUSTOMER == SAC)  
    //GPIO_OutputControl(CAM_EN, FALSE);
    //GPIO_OutputControl(AF_EN, TRUE);
    //GPIO_OutputControl(LED_READY, TRUE);
    #endif

    #if (CUSTOMER == LIT)  
    GPIO_OutputControl(CAM_EN, FALSE);
    GPIO_OutputControl(SUSPEND_EN, TRUE);
    GPIO_OutputControl(LED_READY, FALSE);
    GPIO_OutputControl(CNX_PWR_EN, FALSE);
    GPIO_OutputControl(CNX_RST, FALSE);
    GPIO_OutputControl(MOV_TRIG, FALSE);
    #endif

    #if (CUSTOMER == NKT)  
    GPIO_OutputControl(CAM_EN, FALSE);
    GPIO_OutputControl(SUSPEND_EN, TRUE);
    GPIO_OutputControl(LED_READY, FALSE);
    GPIO_OutputControl(CNX_PWR_EN, TRUE);
    GPIO_OutputControl(AMP_CTRL, FALSE);
    GPIO_OutputControl(AF_EN, FALSE);
    #endif

    #if ((CUSTOMER == LGT) && (MODEL == 0)) 
    GPIO_OutputControl(CAM_EN, FALSE);
    GPIO_OutputControl(LED_READY, TRUE);
    GPIO_OutputControl(WM_PWR_EN, FALSE);
    #endif

    #if ((CUSTOMER == LGT) && (MODEL == 1)) 
    GPIO_OutputControl(CAM_EN, FALSE);
    GPIO_OutputControl(LED_READY, TRUE);
    GPIO_OutputControl(CNX_PWR_EN, FALSE);
    GPIO_OutputControl(CNX_RST, FALSE);
    #endif

    #if ((CUSTOMER == CCN) && (MODEL == 0)) 
    GPIO_OutputControl(CAM_EN, FALSE);
    GPIO_OutputControl(LED_READY, TRUE);
    GPIO_OutputControl(WM_PWR_EN, FALSE);
    #endif

    #if (CUSTOMER == SNO) 
    GPIO_OutputControl(CAM_EN, FALSE);
    #endif

    #if (CUSTOMER == ANW) 
    GPIO_OutputControl(LED_READY, FALSE);
    GPIO_OutputControl(CNX_RST, TRUE);
    #endif

    #if (CUSTOMER == LON)
    GPIO_OutputControl(CAM_EN, FALSE);
    GPIO_OutputControl(LED_READY, FALSE);
    GPIO_OutputControl(TORCH, FALSE);
    #endif

    #if (CUSTOMER == ASU)
    GPIO_OutputControl(CAM_EN_5M, TRUE);
    GPIO_OutputControl(CAM_EN_1M, TRUE);
    GPIO_OutputControl(AF_EN, TRUE);
    #if (MODEL != 0)
    //GPIO_OutputControl(CAM_PWR_EN, FALSE);
    GPIO_OutputControl(CAM_PWR_EN, TRUE);//fix start preview inrush current 800mA to fit ASU REQ 400mA(LITEON check)
    #endif
    GPIO_OutputControl(LED_READY, FALSE);
    #endif

	#if ((CUSTOMER == CCN) && (MODEL == 2)) 
    GPIO_OutputControl(CAM_EN, FALSE);
    GPIO_OutputControl(LED_READY, FALSE);
    #endif

	//m_PreviewControlSem = MMPF_OS_CreateSem(0); 
	//m_StartPreviewFrameEndSem = MMPF_OS_CreateSem(0);

	MMPF_Sensor_ConfigFunctions(gbCurrentSensor);

    waitFlags = SYS_FLAG_SENSOR;
    #if (USE_TASK_DO3A == 1)
    waitFlags |= SYS_FLAG_ISP_AE_START;
    #endif
    #if ((defined(DSC_MP3_P_FW)||(DSC_R_EN))&&(FDTC_SUPPORT == 1))
    waitFlags |= SYS_FLAG_FDTC_DRAWRECT;
    #endif
    #if (SUPPORT_OSD_FUNC)
    waitFlags |= (SYS_FLAG_IBC0_PRERDY | SYS_FLAG_IBC1_PRERDY);
    #endif

    while (TRUE) {
        MMPF_OS_WaitFlags(SYS_Flag_Hif, waitFlags, MMPF_OS_FLAG_WAIT_SET_ANY | OS_FLAG_CONSUME, 0, &flags);

    	#if (USE_TASK_DO3A == 1)
        if (flags & SYS_FLAG_ISP_AE_START) {
        	//gsSensorFunction->MMPF_Sensor_Do3AOperation();
   		    gsSensorFunction->MMPF_Sensor_DoAFOperation_FrameStart();
    		gsSensorFunction->MMPF_Sensor_DoAEOperation_ST();
			gsSensorFunction->MMPF_Sensor_DoAWBOperation();//1031
    	#if IQ_OPR_DMA_ON	
    		gsSensorFunction->MMPF_Sensor_DoIQOperation();
    	#endif
        }
    	#endif
        #if ((defined(DSC_MP3_P_FW)||(DSC_R_EN))&&(FDTC_SUPPORT == 1))
        if (flags & SYS_FLAG_FDTC_DRAWRECT) {
            MMPF_FDTC_DrawFaceRectangles();
            MMPF_FDTC_DrawFrameDoneTrigger();
        }
        #endif

        #if (SUPPORT_OSD_FUNC)
        if (flags & SYS_FLAG_IBC0_PRERDY) {
            vidFmt = pcam_get_info()->pCamVideoFormat;
            if(vidFmt == PCAM_USB_VIDEO_FORMAT_H264){

#if (MOVE_OSD_USING_DMA == 0)  // don't use DMA
                AITPS_IBC   pIBC    = AITC_BASE_IBC;
                volatile AITPS_IBCP pIbcPipeCtl;
                MMP_ULONG y_buf_addr, u_buf_addr;

                pIbcPipeCtl = &(pIBC->IBCP_0);
                //dbg_printf(3, "=PreRdy(0)=\r\n");   
                y_buf_addr = pIbcPipeCtl->IBC_ADDR_Y_ST;
                u_buf_addr = pIbcPipeCtl->IBC_ADDR_U_ST;
                pcam_Osd_ConfigCurrentStream(OSD_CurrentW[0], OSD_CurrentH[0]);
                pcam_SetOsdString2YuvBuffer(strTimeDate, STRLEN(strTimeDate), y_buf_addr, u_buf_addr, OSD_CurrentW[0]);

                pIbcPipeCtl = &(pIBC->IBCP_1);
                //dbg_printf(3, "=PreRdy(1)=\r\n");   
                y_buf_addr = pIbcPipeCtl->IBC_ADDR_Y_ST;
                u_buf_addr = pIbcPipeCtl->IBC_ADDR_U_ST;
                pcam_Osd_ConfigCurrentStream(OSD_CurrentW[1], OSD_CurrentH[1]);
                pcam_SetOsdString2YuvBuffer(strTimeDate, STRLEN(strTimeDate), y_buf_addr, u_buf_addr, OSD_CurrentW[1]);

#else  // using DMA

                //dbg_printf(3, "*OSD Start....");   
                if(gbOSDWordCntChange == 1){
            #if (CUSTOMER == ANW)
                    if(ubOSDTimeFmt == 1)  // 12Hour
                        gsOSD_WIDTH_MAX_WORD = 24;
                    else  // 24 Hour
                        gsOSD_WIDTH_MAX_WORD = 21;
            #else
                    gsOSD_WIDTH_MAX_WORD = 20;
            #endif

                    AllocateOSDYUVBuffer(glOSDStartBufAddr);
                    gbOSDWordCntChange = 0;
                }

                pcam_Osd_ConfigCurrentStream(OSD_CurrentW[0], OSD_CurrentH[0]);
                // Write 1st line into OSD buffer 0
                pcam_SetOsdString2YuvBuffer(strTimeDate, STRLEN(strTimeDate), glOSDBufferYAddr[0], glOSDBufferUVAddr[0], (gsOSD_WIDTH_MAX_WORD*OSD_FontW[0]));
                gsOSDLineNum = 1;
                if(STRLEN(strCustomerData) > 0){
                    // Write 2nd line into OSD buffer 0
                    pcam_SetOsdString2YuvBuffer(strCustomerData, STRLEN(strCustomerData), glOSDBufferYAddr[0]+((gsOSD_WIDTH_MAX_WORD*OSD_FontW[0])*OSD_FontH[0]),
                                                glOSDBufferUVAddr[0]+((gsOSD_WIDTH_MAX_WORD*OSD_FontW[0])*OSD_FontH[0]/2), (gsOSD_WIDTH_MAX_WORD*OSD_FontW[0]));
                    gsOSDLineNum = 2;
                }

                pcam_Osd_ConfigCurrentStream(OSD_CurrentW[1], OSD_CurrentH[1]);
                // Write 1st line into OSD buffer 1
                pcam_SetOsdString2YuvBuffer(strTimeDate, STRLEN(strTimeDate), glOSDBufferYAddr[1], glOSDBufferUVAddr[1], (gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]));
                gsOSDLineNum = 1;
                if(STRLEN(strCustomerData) > 0){
                    // Write 2nd line into OSD buffer 1
                    pcam_SetOsdString2YuvBuffer(strCustomerData, STRLEN(strCustomerData), glOSDBufferYAddr[1]+((gsOSD_WIDTH_MAX_WORD*OSD_FontW[1])*OSD_FontH[1]),
                                                glOSDBufferUVAddr[1]+((gsOSD_WIDTH_MAX_WORD*OSD_FontW[1])*OSD_FontH[1]/2), (gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]));
                    gsOSDLineNum = 2;
                }
                
                //dbg_printf(3, "End=\r\n");   

#endif
            }
        }

        if (flags & SYS_FLAG_IBC1_PRERDY) {
            vidFmt = pcam_get_info()->pCamVideoFormat;
            if(vidFmt == PCAM_USB_VIDEO_FORMAT_H264){
#if (MOVE_OSD_USING_DMA == 0)  // don't use DMA
                AITPS_IBC   pIBC    = AITC_BASE_IBC;
                volatile AITPS_IBCP pIbcPipeCtl;
                MMP_ULONG y_buf_addr, u_buf_addr;

                pIbcPipeCtl = &(pIBC->IBCP_1);
                //dbg_printf(3, "=PreRdy(1)=\r\n");   
                y_buf_addr = pIbcPipeCtl->IBC_ADDR_Y_ST;
                u_buf_addr = pIbcPipeCtl->IBC_ADDR_U_ST;
                pcam_Osd_ConfigCurrentStream(OSD_CurrentW[1], OSD_CurrentH[1]);
                pcam_SetOsdString2YuvBuffer(strTimeDate, STRLEN(strTimeDate), y_buf_addr, u_buf_addr, OSD_CurrentW[1]);
#else  // using DMA
                //dbg_printf(3, "*OSD Start...."); 
  
                if(gbOSDWordCntChange == 1){
                    gsOSD_WIDTH_MAX_WORD = 20;
                    AllocateOSDYUVBuffer(glOSDStartBufAddr);
                    gbOSDWordCntChange = 0;
                }

                pcam_Osd_ConfigCurrentStream(OSD_CurrentW[1], OSD_CurrentH[1]);
                // Write 1st line into OSD buffer 1
                pcam_SetOsdString2YuvBuffer(strTimeDate, STRLEN(strTimeDate), glOSDBufferYAddr[1], glOSDBufferUVAddr[1], (gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]));
                gsOSDLineNum = 1;
                if(STRLEN(strCustomerData) > 0){
                    // Write 2nd line into OSD buffer 1
                    pcam_SetOsdString2YuvBuffer(strCustomerData, STRLEN(strCustomerData), glOSDBufferYAddr[1]+((gsOSD_WIDTH_MAX_WORD*OSD_FontW[1])*OSD_FontH[1]),
                                                glOSDBufferUVAddr[1]+((gsOSD_WIDTH_MAX_WORD*OSD_FontW[1])*OSD_FontH[1]/2), (gsOSD_WIDTH_MAX_WORD*OSD_FontW[1]));
                    gsOSDLineNum = 2;
                }
                //dbg_printf(3, "End=\r\n");   
#endif
            }
        }

        #endif        
    }
}

#if 0 // Controls for color trans move to scaler
//Steven 20111107 ADD
const MMP_UBYTE gColorTransform[] = {
	0xFF, 0x91, 0xB8, 0x01, 0x80, 0x80, // Y:  0-255, U:  0-255, V:  0-255
//	0xDC, 0x91, 0xB8, 0x10, 0x80, 0x80, // Y: 16-235, U:  0-255, V:  0-255
	0xDC, 0x7E, 0xA0, 0x10, 0x80, 0x80, // Y: 16-235, U:  0-224, V:  0-224
//	0xFF, 0x91, 0xB8, 0x01, 0x80, 0x80, //	0xF0, 0x91, 0xB8, 0x10, 0x80, 0x80, // Y: 16-255, U:  0-255, V:  0-255
	255, 0x91, 0xB8, 7, 0x80, 0x80, // Y: 16-255, U:  0-255, V:  0-255
};

MMP_ERR MMPF_Sensor_SetColorTransform(MMP_UBYTE range)
{
	MMP_USHORT i;
	MMP_USHORT offset 	= range * 6;
	MMP_UBYTE *ISP_XBYTE = (MMP_UBYTE *)AITC_BASE_ISP;
	for (i = 0; i < 6; i++) {
	    // FIXME!!!
		ISP_XBYTE[0x75 + i] = gColorTransform[offset + i];
	}
	return MMP_ERR_NONE;
}
#endif


#endif
/// @}
